package com.yu1996.gulimall.gulimall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.yu1996.common.constant.AuthServerConstant;
import com.yu1996.common.exception.BizCodeEnume;
import com.yu1996.common.utils.R;
import com.yu1996.common.vo.MemberRespVo;
import com.yu1996.gulimall.gulimall.auth.feign.MemberFeignService;
import com.yu1996.gulimall.gulimall.auth.feign.ThirdPartFeignService;
import com.yu1996.gulimall.gulimall.auth.vo.UserLoginVo;
import com.yu1996.gulimall.gulimall.auth.vo.UserRegisterVo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Slf4j
@Controller
public class LoginController {

  @Autowired private ThirdPartFeignService thirdPartFeignService;

  @Autowired private StringRedisTemplate redisTemplate;

  @Autowired private MemberFeignService memberFeignService;
  /**
   * 用户认证登录方法 成功重定向到首页 失败重定向到登录页
   *
   * @return
   */
  @PostMapping("/login")
  public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session) {
    R r = memberFeignService.login(vo);
    if (r.getCode() == 0) {
      // 登录成功
      MemberRespVo memberRespVo = r.getData("data", new TypeReference<MemberRespVo>() {});
      session.setAttribute(AuthServerConstant.LOGIN_USER, memberRespVo);
      // redirectAttributes.addFlashAttribute("member", r.get("data"));
      return "redirect:http://gulimall.com";
    } else {
      // 登录失败
      redirectAttributes.addFlashAttribute("errors", r.get("msg"));
      return "redirect:http://auth.gulimall.com/login.html";
    }
  }

  // TODO:重定向携带数据  分布式下的session问题
  @PostMapping("/register")
  public String register(
      @Valid UserRegisterVo userVo, BindingResult result, RedirectAttributes redirectAttributes) {
    // RedirectAttributes: 重定向携带数据   是利用session存储数据  只要跳到下一个页面取出数据后  session就会删除数据
    while (result.hasErrors()) {
      // Map<String, String> errors =
      //    result.getFieldErrors().stream()
      //        .collect(Collectors.toMap(FieldError::getField,
      // FieldError::getDefaultMessage,(entity1,entity2){
      //          return entity1;
      // }));
      // redirectAttributes.addFlashAttribute("errors", errors);
      Map<String, String> errors = new HashMap<>();
      List<FieldError> fieldErrors = result.getFieldErrors();
      for (FieldError fieldError : fieldErrors) {
        errors.put(fieldError.getField(), fieldError.getDefaultMessage());
      }
      redirectAttributes.addFlashAttribute("errors", errors);
      return "redirect:http://auth.gulimall.com/reg.html";
    }
    // 格式校验没有问题  校验验证码
    String codeForRedis =
        redisTemplate
            .opsForValue()
            .get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userVo.getPhone());
    // 判断code不为空
    if (!StringUtils.isEmpty(codeForRedis)) {
      String code = codeForRedis.split("_")[0];
      if (code.equals(userVo.getCode())) {
        // 删除验证码的缓存  令牌机制
        redisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userVo.getPhone());
        // 进行真正的注册服务
        R r = memberFeignService.regist(userVo);
        if (r.getCode() == 0) {
          // 注册成功

          return "redirect:http://auth.gulimall.com/login.html";
        } else {
          // 注册出错
          Map<String, String> errors = new HashMap<>();
          errors.put("msg", r.getData("msg", new TypeReference<String>() {}));
          redirectAttributes.addFlashAttribute("errors", errors);
          return "redirect:http://auth.gulimall.com/reg.html";
        }
      } else {
        // 验证码错误  返回错误信息
        Map<String, String> errors = new HashMap<>();
        errors.put("code", "验证码错误");
        redirectAttributes.addFlashAttribute("errors", errors);
        return "redirect:http://auth.gulimall.com/reg.html";
      }
    } else {
      // 验证码不存在  返回错误信息
      Map<String, String> errors = new HashMap<>();
      errors.put("code", "验证码错误");
      redirectAttributes.addFlashAttribute("errors", errors);
      return "redirect:http://auth.gulimall.com/reg.html";
    }
  }

  @GetMapping("/login.html")
  public String loginPage(HttpSession session) {
    Object loginUser = session.getAttribute(AuthServerConstant.LOGIN_USER);
    if (loginUser != null) {
      return "redirect:http://gulimall.com";
    } else {
      return "login";
    }
  }

  @ResponseBody
  @RequestMapping("/sms/sendcode")
  public R sendCode(@RequestParam("phone") String phone) {
    // 校验验证码防止多次发送
    String codeStr =
        redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
    if (!StringUtils.isEmpty(codeStr)) {
      long longTime = Long.parseLong(codeStr.split("_")[1]);
      // 判断是否60s内多次发送
      if (System.currentTimeMillis() - longTime < 60000L) {
        return R.error(
            BizCodeEnume.SMS_CODE_EXCEPTION.getCode(), BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
      }
    }
    // 生成验证码
    String code = UUID.randomUUID().toString().substring(0, 6);
    redisTemplate
        .opsForValue()
        .set(
            AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone,
            code + "_" + System.currentTimeMillis(),
            AuthServerConstant.SMS_CODE_CACHE_EXCEPTION_TIME,
            TimeUnit.MINUTES);
    thirdPartFeignService.sendCode(phone, code);
    return R.ok();
  }
}
